package org.hako.recite.word.test;

import java.util.Set;

import org.hako.recite.word.dict.FindMeaningException;
import org.hako.recite.word.dict.MeaningFinder;
import org.hako.recite.word.dict.impl.LinkMeaningFinder;
import org.hako.recite.word.words.WordSet;

/**
 * Resource of word test that contains word set, test profile and result.
 * 
 * @author <a href="mailto:xnnyygn@gmail.com">XnnYygn</a>
 */
public class WordTestResource {

    private WordSet words;
    private WordTestProfile profile;
    private WordTestResult result;
    private MeaningFinder meaningFinder;

    /**
     * Create
     * 
     * @param words
     * @param profile 
     */
    public WordTestResource(WordSet words, WordTestProfile profile) {
        super();
        this.words = words;
        this.profile = profile;
        result = new WordTestResult();
        meaningFinder = new LinkMeaningFinder();
    }

    /**
     * Get question count.
     * 
     * @return 
     */
    public int getQuestionCount() {
        return profile.getWordLimit();
    }

    /**
     * Get question.
     * 
     * @param index
     * @return 
     */
    public String getQuestion(int index) {
        return words.get(profile.getQuestionFieldIndex(), index);
    }

    /**
     * Get answer.
     * 
     * @param index
     * @return 
     */
    public String getAnswer(int index) {
        return words.get(profile.getAnswerFieldIndex(), index);
    }

    /**
     * Add wrong word index.
     * 
     * @param index 
     */
    public void addWrong(int index) {
        result.addWrong(index);
    }

    /**
     * Get wrong words index.
     * 
     * @return 
     */
    public Set<Integer> getWrongs() {
        return result.getWrongs();
    }

    /**
     * Find meaning of word.
     * 
     * @param index
     * @return
     */
    public String findMeaning(int index) {
        try {
            return meaningFinder.find(getQuestion(index));
        } catch (FindMeaningException e) {
            return "Failed to find meaning, error message is [" 
                    + e.getMessage() + "]";
        }
    }
    
    /**
     * Clear wrongs.
     */
    public void clearWrongs(){
        result.clearWrongs();
    }
    
    /**
     * Check retest wrongs.
     * 
     * @return 
     */
    public boolean shouldRetestWrongs(){
        return profile.isRetestWrongs();
    }
    
    /**
	 * Generate report of wrong words.
	 * 
	 * @return test report
	 */
	public String generateWrongWordsReport() {
		StringBuilder builder = new StringBuilder();
		builder.append("Wrong words count: ");
		builder.append(getWrongs().size());
		builder.append('\n');
		for (Integer questionId : getWrongs()) {
			builder.append(getQuestion(questionId.intValue()));
			builder.append(" \t");
			builder.append(getAnswer(questionId.intValue()));
			builder.append('\n');
		}
		return builder.toString();
	}
}
